#include <iostream>
#include <sys/shm.h>

#include <QtGui>
#include <GL/glew.h>
#include <QGLWidget>
#include <GL/glut.h>

#include <iostream>
#include <vector>

#include "Timer/timer.01.h"
#include "floor.h"

#define SQR(x) ((x)*(x))

using namespace std;

typedef double T;
/*
class Floor {
	public:
		T h; // height
		T x;
		T v;
		T a;
		T m;
		bool fixed;
};
*/


class Visualizator: public QGLWidget {

	public:
		
		float timeStep;
		float timeFlag;
		
		Timer wallTime;
		int glTimerID, fpsTimerID;
		
		int frames;
		double framesTime;
		double fps;
		
		long double Etot0;
		
		//vector<Floor> f;
		
		Visualizator(QWidget *parent=0): QGLWidget(parent),
		timeStep(27), // [ms]
		frames(0),
		framesTime(0),
		fps(0)
		{ 
			
			//o.resize(*(uint*)att_shm(100, 4, NULL));
			
			
			//return shmat(id, NULL, 0);
			
			
			/*for (uint i=0; i<o.size(); i++)
				o[i] = ((Object*)att_shm(911, o.size()*sizeof(Object), NULL))[i];
			*/
			setAutoFillBackground(false);
			wallTime.set();
			wallTime.sin = 0.001*timeStep;
			glTimerID = startTimer(timeStep);
			fpsTimerID = startTimer(250); // fps info time
			timeFlag = true;
			
		};
		
		void *att_shm(int key, uint size, char *addr){
			shmdt(addr);
			int id = shmget(key, size, 0666); // set seg with 'key' and 'size'
			return shmat(id, NULL, 0);
		}
		
		
		void timerEvent(QTimerEvent *event) {
			
			if (event->timerId() == glTimerID) {
				
				wallTime.set();
				if (timeFlag) moveTime(wallTime.sin+wallTime.sout);
				updateGL();
				
				framesTime+=wallTime.sin+wallTime.sout;
				frames++;
				wallTime.get();
				
			}
			
			if (event->timerId() == fpsTimerID){
				fps = frames/framesTime;
				framesTime=frames=0;
			}
			
			
		}
		
		virtual void moveTime(double dt){
			//printf("o[0].x = %g\n", o[0].x);
		}
		
		virtual void initializeGL() {  // Set up the rendering context, define display lists etc.:

			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
			glShadeModel(GL_FLAT);
			glClearDepth(1.0);							// Enables Clearing Of The Depth Buffer
			glDepthFunc(GL_LESS);
			glEnable(GL_DEPTH_TEST);					// Enables Depth Testing
			glEnable(GL_CULL_FACE);
			
		}

		void resizeGL(int w, int h){  // setup viewport, projection etc.:
			glViewport(0, 0, w, h);
		}
		
		virtual void paintGL() {
			
			
			
			int id_n = shmget(9110, 4, 0666);
			//std::cout <<id_n << std::endl;
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			if (id_n==-1) return;
			uint &N = *(uint*)shmat(id_n, NULL, 0);
			
			int id_f = shmget(9111, N*sizeof(Floor), 0666);
			Floor *f = (Floor*)shmat(id_f, NULL, 0);
			

			glMatrixMode ( GL_PROJECTION );
			glLoadIdentity(); // загружает еденичную матрицу
			
			float aspect = (float)width()/height();
			
			glOrtho(-aspect, +aspect, 0, 1, -1000, 1000);
			
			glMatrixMode(GL_MODELVIEW); 
			glLoadIdentity();
			
			//std::cout << id << std::endl;
			
			
			for (uint i=0; i<N; i++) {
				//printf("%g\n", f[i].color.r);
				glColor4fv(f[i].color);
				glRectangle(f[i].x, f[i].h);	
			}
			
			shmdt(&N);
			shmdt(f);
		}


	
		virtual void keyPressEvent(QKeyEvent *event){
			
			if (event->key() == Qt::Key_F) 
				setWindowState(windowState()^Qt::WindowFullScreen);
			
			if (event->key() == Qt::Key_Space)
				timeFlag = !timeFlag;
			
			if (event->key() == Qt::Key_Escape)
				if (windowState()) setWindowState(windowState()^Qt::WindowFullScreen);
				else exit(0);
				
		}
		
		
		void glRectangle(float y, float h) {
			
			float w = 0.5;
			
			glBegin(GL_QUADS);
			glVertex2f(-.5*w, y-.5*h);
			glVertex2f(+.5*w, y-.5*h);
			glVertex2f(+.5*w, y+.5*h);
			glVertex2f(-.5*w, y+.5*h);
			
			glEnd();	
		}
		
		void glPrint(int x, int y, const char *string, void *font) {
	
			// save current projection matrix
			glMatrixMode(GL_PROJECTION); 
			glPushMatrix();
	
			// get viewport size
			GLint viewport[4];
			glGetIntegerv(GL_VIEWPORT, viewport );
	
			// set projection matrix to ortho settings
			glLoadIdentity();
			glOrtho(0, viewport[2], viewport[3], 0, -1, 1);
	
			// save current modelview matrix
			glMatrixMode(GL_MODELVIEW); 
			glPushMatrix();
	
			//text drowing
			glLoadIdentity();

			int indent = 15; //
			glRasterPos2i(x, y);
			int len = (int) strlen(string);
			for (int i = 0; i < len; i++) {
		
				if (string[i] == '\n') {
					y+=indent;
					glRasterPos2i(x, y);
					continue;
				}
				glutBitmapCharacter(font, string[i]);
		
			}
	
			// restore previos settings
			glMatrixMode(GL_PROJECTION); 
			glPopMatrix();
	
			glMatrixMode(GL_MODELVIEW); 
			glPopMatrix();
			
		}
	
		
};



int main(int argc, char *argv[]) {
	
	glutInit(&argc, argv); //initialize glut
	QApplication app(argc, argv);
	
	Visualizator visualizator;
	visualizator.resize(200, 600);
	visualizator.setWindowTitle( QString("Visualizator Lite for 911") );
	visualizator.show();
	
	return app.exec();
	
	
}

